using System.Collections.Generic;
using WCell.RealmServer.Entities;
using WCell.RealmServer.GameObjects;
using WCell.RealmServer.Global;
using WCell.RealmServer.Guilds;
using WCell.Constants;
using WCell.Constants.NPCs;
using WCell.RealmServer.NPCs;
using Castle.ActiveRecord;
using WCell.Util.Graphics;
using WCell.Constants.World;
using WCell.Core.Timers;

namespace Kingdoms
{
    public abstract class Territory
    {
        private TerritoryTemplate _template;
        private List<KingdomGuard> _guards;
        public TimerEntry captureTimer;
        public TimerEntry upgradeTimer;

        private TerritoryDatabase databaseAccess;

        protected Territory(TerritoryTemplate template)
        {
            _template = template;
            // TODO: FIX.
            Flag = GOMgr.GetEntry(template.Flag).Templates.GetClosestTemplate(Flag).Spawn(template.Region);
            foreach (ZoneInfo z in Template.ZoneInfos) 
            { 
                z.PlayerEntered += OnEnter; 
            }
            IsBeingUpgraded = false;
            LoadFromDB();
            /*
            foreach (KingdomGuard guard in KingdomNPCMgr.Guards.Values)
            {
                if (guard.TerritoryID == template.Id)
                {
                    _guards.Add(guard);
                }
            }
             */
        }


        /// <summary>
        /// The template this territory was built from.
        /// </summary>
        public TerritoryTemplate Template
        {
            get { return _template; }
        }

        /// <summary>
        /// Id of this territory
        /// </summary>
        public int Id
        { 
            get { return Template.Id;}
        }

        /// <summary>
        /// Current owner of this territory
        /// </summary>
        public Guild Owner;

        /// <summary>
        /// Whether the territory is currently being upgraded
        /// </summary>
        public bool IsBeingUpgraded
        {
            get;
            private set;
        }

        /// <summary>
        /// A string representing what is currently being upgraded
        /// </summary>
        public string WhatIsBeingUpgraded
        {
            get;
            private set;
        }

        /// <summary>
        /// The subzones of this territory
        /// </summary>
        public List<Zone> Zones
        {
            get { return Template.Zones; }
        }

        /// <summary>
        /// The flag representing this territory
        /// Capturing the flag will capture the territory.
        /// </summary>
        public GameObject Flag
        {
            get; set;
        }

        

        /// <summary>
        /// Loads stuff from the DB and sets ownership
        /// </summary>
        private void LoadFromDB()
        {
            try
            {
                databaseAccess = TerritoryDatabase.Find(Id);
            }
            catch
            {
                databaseAccess = new TerritoryDatabase();
            }
            Guild guild = GuildMgr.GetGuild(databaseAccess.GuildID);
            if (guild == null)
            {
                Reset();
                if(KingdomGuildMgr.Guilds.ContainsKey(databaseAccess.GuildID))
                {
                    KingdomGuildMgr.Guilds.Remove(databaseAccess.GuildID);
                }
                //In case of issues, do shit here.
            }
        }

        /// <summary>
        /// Saves everthing related to a territory to the DB
        /// </summary>
        private void SaveToDb()
        {
            databaseAccess.GuildID = Owner.Id;
            databaseAccess.Id = Id;
            databaseAccess.Save();
        }

        /// <summary>
        /// Starts the territory.
        /// </summary>
        public void Start()
        {
            Template.FixGOs();
            HookUpGOs();
            if (Owner != null)
            {
                var owner = KingdomGuildMgr.Guilds[Owner.Id];
                owner.OwnedTerritories.Add(this);
            }
            SpawnTerritory();
        }
        /// <summary>
        /// Calculates the upkeep costs
        /// </summary>
        public int CostPerUpkeep()
        {
            int cost = 0;
            cost += Template.UpgradeTrainingLevelCost;
            cost += Template.UpgradeExperienceLevelCost;;
            cost += cost * Template.UpgradeExperienceLevelCost / 100;
            return cost;
        }

        private void SpawnTerritory()
        {
            if (Owner != null)
            {
                foreach(NPCDatabaseEntry entry in KingdomNPCMgr.Guards.Values)
                {
                    if (entry.TerritoryID == Id)
                    {
                        switch (entry.GuardType)
                        {
                            case (int)GuardEnum.GuardBrute:
                                {
                                    var g = NPCMgr.GetEntry(KingdomNPCMgr.GetGuardNPCEntry(Owner, GuardEnum.GuardBrute));
                                    var guard = (GuardBrute)g.Create();
                                    guard.dbentry = entry;

                                    Vector3 location = new Vector3(entry.X, entry.Y, entry.Z);
                                    guard.AddSpawnEntry(guard.dbentry.MapID, location, 1, guard.dbentry.RespawnTime, guard.dbentry.RespawnTime);
                                    guards.Add(guard.dbentry.Id, guard);
                                    guard.spawn
                                    break;
                                }
                            
                            case (int)GuardEnum.GuardCleric:
                                {
                                    break;
                                }
                            
                            case (int)GuardEnum.GuardMarksman:
                                {
                                    break;
                                }
                            
                            case (int)GuardEnum.GuardWarlock:
                                {
                                    break;
                                }
                            
                            case (int)GuardEnum.GuardSorcerer:
                                {
                                    break;
                                }




                        }
                    }
                }   
            }
        }

        /// <summary>
        /// Used to change overship from 1 guild to another.
        /// </summary>
        public void Capture(Guild guild)
        {
            ResetToZero();
            TerritoryMgr.OnCapture(guild, this, Owner);
            foreach (KingdomGuard guard in _guards)
            {
                guard.GuildID = guild.Id;
            }
            Owner = guild;
        }

        /// <summary>
        /// Hooks up events to flags.
        /// </summary>
        public void HookUpGOs()
        {
            Flag.Entry.Used += (flag, chr) =>
            {
                if (chr.Guild != null && captureTimer.IsRunning && chr.Guild == Owner)
                    captureTimer.Stop();
                if (chr.Guild != null && chr.Guild != Owner && CanCapture(chr.Guild))
                {
                    captureTimer = Template.Region.CallDelayed(120f, () => Capture(chr.Guild));
                    Capture(chr.Guild); //hook up a timer allowing a guild to recap
                    return true;
                }
                return false;
           };
        }

        /// <summary>
        /// Resets ownership of the territory to zero
        /// </summary>
        public void Reset()
        {
            TerritoryMgr.OnReset(this, Owner);
            if (Owner != null)
            {
                var owner = KingdomGuildMgr.Guilds[Owner.Id];
                owner.OwnedTerritories.Remove(this);
            }
            Owner = null;
            ResetToZero();
        }


        /// <summary>
        /// Reduces the territory to lvl 1 and despawns additional guards.
        /// </summary>
        public void ResetToZero()
        {
            databaseAccess.GuardCountLevel = 1;
            databaseAccess.ExperienceLevel = 1;
            databaseAccess.TrainingLevel = 1;
            foreach (KingdomGuard guard in _guards)
            {
                if (guard.CountLevel > databaseAccess.GuardCountLevel)
                {
                    //despawn da guard
                }
                guard.GuildID = 0;
                guard.TrainingLevel = 1;
                guard.ExperienceLevel = 1;
            }
        }

        /// <summary>
        /// Defines whether an area is capturable
        /// </summary>
        public bool CanCapture(Guild g)
        {
            if (IsLocked)
                return false;
            if (Template.IsOpen)
                return true;
            foreach (Territory t in Template.NeighboringTerritories)
            {
                if (t.Owner == g)
                    return true;
            }
            return false;
        }

        #region Upgrades
        /// <summary>
        /// Upgrades the amount of guards
        /// </summary>
        public void UpgradeGuardCount()
        {
            if ((databaseAccess.GuardCountLevel + 1) > 3)
            {
                return; //add some warning here.
            }

            databaseAccess.GuardCountLevel = databaseAccess.GuardCountLevel + 1;
            IsBeingUpgraded = true;
            WhatIsBeingUpgraded = "Currently upgrading Guard Count to level " + databaseAccess.GuardCountLevel.ToString();
            upgradeTimer = Template.Region.CallDelayed(Template.UpgradeTimeGuardCount, UpgradeGuardCountCallback);
        }


        private void UpgradeGuardCountCallback()
        {
            foreach (KingdomGuard guard in _guards)
            {
                if (guard.CountLevel == databaseAccess.GuardCountLevel)
                {
                    //spawn da guards
                }
            }
            IsBeingUpgraded = false;
            WhatIsBeingUpgraded = null;
        }
        /// <summary>
        /// Downgrades the amount of guards
        /// </summary>
        public void DowngradeGuardCount()
        {
            if ((databaseAccess.GuardCountLevel - 1) < 0)
                return;
            databaseAccess.GuardCountLevel = databaseAccess.GuardCountLevel + 1;
            foreach (KingdomGuard guard in _guards)
            {
                if (guard.CountLevel > databaseAccess.GuardCountLevel)
                {
                    //despawn da guards
                }
            }
        }

        /// <summary>
        /// Upgrades the GuardExperienceLevel.
        /// </summary>
        public void UpgradeGuardExperienceLevel()
        {
            if ((databaseAccess.ExperienceLevel + 1) > 5)
            {
                return; //add some warning here.
            }

            databaseAccess.ExperienceLevel = databaseAccess.ExperienceLevel + 1;
            IsBeingUpgraded = true;
            WhatIsBeingUpgraded = "Currently upgrading Guard Experience to level " + databaseAccess.ExperienceLevel.ToString();
            upgradeTimer = Template.Region.CallDelayed(Template.UpgradeTimeExperienceLevel, UpgradeGuardExperienceLevelCallback);
        }


        private void UpgradeGuardExperienceLevelCallback()
        {
            foreach (KingdomGuard guard in _guards)
            {
                guard.ChangeExperienceLevel(databaseAccess.ExperienceLevel);
            }
            IsBeingUpgraded = false;
            WhatIsBeingUpgraded = null;
        }

        /// <summary>
        /// Downgrades the GuardExperienceLevel.
        /// </summary>
        public void DowngradeGuardExperienceLevel()
        {
            if ((databaseAccess.ExperienceLevel - 1) < 0)
                return;
            databaseAccess.ExperienceLevel = databaseAccess.ExperienceLevel - 1;
            foreach (KingdomGuard guard in _guards)
            {
                guard.ChangeExperienceLevel(databaseAccess.ExperienceLevel);
            }
        }


        /// <summary>
        /// Upgrades the GuardExperienceLevel.
        /// </summary>
        public void UpgradeGuardTrainingLevel()
        {
            if ((databaseAccess.TrainingLevel + 1) > 5)
            {
                return; //add some warning here.
            }

            databaseAccess.TrainingLevel = databaseAccess.TrainingLevel + 1;
            IsBeingUpgraded = true;
            WhatIsBeingUpgraded = "Currently upgrading Guard Training to level " + databaseAccess.TrainingLevel.ToString();
            upgradeTimer = Template.Region.CallDelayed(Template.UpgradeTimeTrainingLevel, UpgradeGuardTrainingLevelCallback);

        }


        private void UpgradeGuardTrainingLevelCallback()
        {
            foreach (KingdomGuard guard in _guards)
            {
                guard.TrainingLevel = databaseAccess.TrainingLevel;
            }
            IsBeingUpgraded = false;
            WhatIsBeingUpgraded = null;
        }

        /// <summary>
        /// Downgrades the GuardExperienceLevel.
        /// </summary>
        public void DowngradeGuardTrainingLevel()
        {
            if ((databaseAccess.TrainingLevel - 1) < 0)
                return;
            databaseAccess.TrainingLevel = databaseAccess.TrainingLevel - 1;
            foreach (KingdomGuard guard in _guards)
            {
                guard.TrainingLevel = databaseAccess.TrainingLevel;
            }
        }

        #endregion
        /// <summary>
        /// Event callback for when a player enters an occopied territory,
        /// </summary>
        private void OnEnter(Character chr, Zone oldZone)
        {
            //send some fancy message to the dude who owns this shit.
        }

        /// <summary>
        /// Whether a territory is locked due to unforseen reasons.
        /// </summary>
        public bool IsLocked
        {
            get;
            private set;
        }
    }
}